using UnityEngine;
using System.Collections;

[RequireComponent(typeof(LineRenderer))]
[RequireComponent(typeof(AutomaticRotation))]
[RequireComponent(typeof(AutomaticTranslation))]
public class Laser : MonoBehaviour
{
    #region Attributes

    public float damage = 0.166666f;
    public float timeSinceHit = 0.0f;
    public float timeOffset = 1.0f;
    public float scrollSpeed = 0.5f;
    public float pulseSpeed = 1.5f;
    public float noiseSize = 1.0f;
    public float maxWidth = 0.5f;
    public float minWidth = 0.3f;
	
	public GameObject particleEffectHitPlayer;
	public GameObject particleEffectHitWall;

    private LineRenderer lRenderer;
    private float aniDir = 1.0f;
    private RaycastHit hitInfo;

    #endregion

    #region Unity Methods

    // Use this for initialization
    void Start()
    {
        this.hitInfo = new RaycastHit();
        this.lRenderer = gameObject.GetComponent<LineRenderer>();

        // Change some animation values here and there
        this.aniDir = this.aniDir * 0.9f + Random.Range(0.5f, 1.5f) * 0.1f;
        this.minWidth = this.minWidth * 0.8f + Random.Range(0.1f, 1.0f) * 0.2f;
    }

    // Update is called once per frame
    void Update()
    {
        int mask = ~TagConstants.LAYER_MARKS;
        // Cast a ray to find out the end point of the laser
        Physics.Raycast(transform.position, transform.forward, out hitInfo, Mathf.Infinity, mask);

        // El segmento LineRenderer tiene 2 puntos: inicial y final (0 y 1)
        // Ponemos el punto inicial del segmento en el propio laser
        this.lRenderer.SetPosition(0, gameObject.transform.position);
        this.lRenderer.material.mainTextureOffset += new Vector2(Time.deltaTime * this.aniDir * this.scrollSpeed, renderer.material.mainTextureOffset.y);
        this.lRenderer.material.SetTextureOffset("_NoiseTex", new Vector2(-Time.time * this.aniDir * this.scrollSpeed, 0.0f));

        // Anima el ancho del laser
        float aniFactor = Mathf.PingPong(Time.time * this.pulseSpeed, 1.0f);
        aniFactor = Mathf.Max(this.minWidth, aniFactor) * this.maxWidth;
        this.lRenderer.SetWidth(aniFactor, aniFactor);

        if (this.hitInfo.transform)
        {
            // Si hay hit ponemos el punto final del segmento en el punto de colision
            this.lRenderer.SetPosition(1, this.hitInfo.point);
            this.lRenderer.material.mainTextureScale = new Vector2(0.1f * (this.hitInfo.distance), renderer.material.mainTextureScale.y);
            this.lRenderer.material.SetTextureScale("_NoiseTex", new Vector2(0.1f * this.hitInfo.distance * this.noiseSize, this.noiseSize));
			
            if (this.hitInfo.collider.tag == TagConstants.TAG_PLAYER)
			{
				GameObject.Instantiate(this.particleEffectHitPlayer, this.hitInfo.point, Quaternion.identity);
				if(this.timeSinceHit + this.timeOffset < Time.timeSinceLevelLoad)
            		{	
                		timeSinceHit = Time.timeSinceLevelLoad;
                		GameControl.FindPlayer().ChangeEnergy(this.damage, false);
					}
            }
			else  if(this.hitInfo.collider.tag == TagConstants.TAG_WALL)
				GameObject.Instantiate(this.particleEffectHitWall, this.hitInfo.point, Quaternion.identity);
        }
        else
        {
            // Si no hay hit ponemos el punto final del segmento en maxDist
            float maxDist = 200.0f;
            this.lRenderer.SetPosition(1, (maxDist * gameObject.transform.forward));
            this.lRenderer.material.mainTextureScale = new Vector2(0.1f * (maxDist), renderer.material.mainTextureScale.y);
            this.lRenderer.material.SetTextureScale("_NoiseTex", new Vector2(0.1f * (maxDist) * this.noiseSize, this.noiseSize));
        }
    }

    #endregion    
}